package com.zh.common.utils

import android.app.Application
import android.content.Intent
import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.fragment.app.Fragment
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.PermissionUtils
import com.zh.common.ktx.registerForResult
import com.zh.common.ktx.toast
import com.zh.config.PerConfig
import java.io.File
import java.util.Locale

/**
 * 文字转音频播放
 * Android 11 以上适配
 * <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
 */
class TtsUtils private constructor() {

    private val TAG = "tts"
    private var time = 0L
    private var application: Application? = null
    private var fileName = "test"
    private var loadEnum = LoadEnum.START_INIT
    private var playEnum = PlayEnum.PLAY_START
    private var mTTS: TextToSpeech? = null
    private var filePath = ""
    private var launcher: ActivityResultLauncher<Intent>? = null

    companion object {
        @JvmStatic
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { TtsUtils() }
    }

    enum class LoadEnum {
        START_INIT,//初始化
        LOADING,//开始缓存文件
        LOADED;//完成缓存文件
    }

    enum class PlayEnum {
        PLAY_START,//开始播放
        PLAY_DONE,//播放完成
        PLAY_ERROR;//播放错误
    }

    fun init(application: Application) {
        this.application = application
    }

    private fun loadTTs(callback: (Boolean) -> Unit = {}) {
        loadEnum = LoadEnum.START_INIT
        mTTS = TextToSpeech(application) { status: Int ->
            if (status == TextToSpeech.SUCCESS) {
                val result = mTTS?.setLanguage(Locale.CHINESE)
                if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
                    // 语言设置不支持，处理逻辑
                    Log.d(TAG, "不支持该语言")
                    callback.invoke(false)
                } else {
                    // TextToSpeech初始化成功
                    Log.d(TAG, "tts初始化成功")
                    // 设置音调：值越大声音越尖（女生），值越小则变成男声，1.0是常规，语调范围从0.5到2.0
                    mTTS?.setPitch(1.0f)
                    // 设定语速：默认1.0正常语速，语速范围从0.1到2.0
                    mTTS?.setSpeechRate(1.0f)
                    callback.invoke(true)
                }
            } else {
                Log.d(TAG, "tts初始化失败")
                callback.invoke(false)
            }
        }
    }

    /**
     * 将文字内容转换成音频保存本地
     * 返回文件路径
     */
    fun synthesizeTextToFile(text: String, callback: (String) -> Unit) {
        PermissionUtils.permission(*PerConfig.sdcard.toTypedArray())
            .callback { isAllGranted, _, _, _ ->
                if (isAllGranted) {
                    val filePath = getAudioFilePath()
                    val file = File(filePath)
                    if (mTTS != null && (!file.exists() || (file.exists() && file.length() == 0L))) {
                        loadEnum = LoadEnum.LOADING
                        val synthesizeToFile =
                            mTTS?.synthesizeToFile(text, null, file, "audio")
                        Log.d(TAG, "synthesizeToFile = $synthesizeToFile")
                    } else {
                        loadEnum = LoadEnum.LOADED
                    }
                    callback.invoke(filePath)
                } else {
                    "需要同意文件存储权限".toast()
                }
            }.request()
    }

    private fun getAudioFilePath(): String {
        val audioFolder = File(application?.externalCacheDir, "Audio")
        if (!audioFolder.exists()) {
            audioFolder.mkdirs()
        }
        return audioFolder.absolutePath + File.separator + fileName + ".mp4"
    }

    /**
     * TextToSpeech.QUEUE_FLUSH 表示直接清空播放队列
     * TextToSpeech.QUEUE_ADD   多个语音添加到播放队列中依次播放
     */
    fun speak(content: String) {
        mTTS?.let {
            if (it.isSpeaking) it.stop()
            it.speak(content, TextToSpeech.QUEUE_FLUSH, null, "tts")
        }
    }

    fun stop() {
        mTTS?.stop() // 不管是否正在朗读TTS都被打断
    }

    fun release() {
        if (loadEnum == LoadEnum.LOADING) {
            kotlin.runCatching {
                FileUtils.delete(filePath)
            }.onFailure { it.printStackTrace() }
        }
        mTTS?.stop() // 不管是否正在朗读TTS都被打断
        mTTS?.shutdown() // 关闭，释放资源
        mTTS = null
    }

    fun listener(callback: (LoadEnum?, PlayEnum) -> Unit) {
        mTTS?.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
            override fun onStart(utteranceId: String?) {
                cTime {
                    playEnum = PlayEnum.PLAY_START
                    callback.invoke(null, playEnum)
                }
            }

            override fun onDone(utteranceId: String?) {
                cTime {
                    playEnum = PlayEnum.PLAY_DONE
                    loadEnum = LoadEnum.LOADED
                    callback.invoke(loadEnum, playEnum)
                }
            }

            override fun onError(utteranceId: String?) {
                cTime {
                    playEnum = PlayEnum.PLAY_ERROR
                    callback.invoke(null, playEnum)
                }
            }
        })
    }

    //防止重复加载
    private fun cTime(callback: () -> Unit) {
        if (System.currentTimeMillis() - time > 800) {
            callback.invoke()
        }
        time = System.currentTimeMillis()
    }

    /**
     * 判断TextToSpeech是否安装, 并且初始化
     */
    fun checkTTSEngineAndInit() {
        val checkIntent = Intent()
        checkIntent.action = TextToSpeech.Engine.ACTION_CHECK_TTS_DATA
        launcher?.launch(checkIntent)
    }

    /**
     * 这里返回初始化完成
     */
    fun launcherActivity(activity: ComponentActivity, callback: (Boolean) -> Unit = {}) {
        launcher = activity.registerForResult {
            if (it.resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                loadTTs { callback.invoke(it) }
            } else {
                val installIntent = Intent()
                installIntent.action = TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
                activity.startActivity(installIntent)
            }
        }
    }

    /**
     * 这里返回初始化完成
     */
    fun launcherFragment(fragment: Fragment, callback: (Boolean) -> Unit = {}) {
        launcher = fragment.registerForResult {
            if (it.resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                loadTTs { callback.invoke(it) }
            } else {
                val installIntent = Intent()
                installIntent.action = TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
                fragment.startActivity(installIntent)
            }
        }
    }
}